package com.vimhe.easyimport.reader;

import com.vimhe.easyimport.config.ImportConfig;
import com.vimhe.easyimport.config.bean.CellConfig;
import com.vimhe.easyimport.config.bean.FileConfig;
import com.vimhe.easyimport.config.bean.RowConfig;
import com.vimhe.easyimport.config.bean.SheetConfig;
import com.vimhe.easyimport.filter.DataFilterChain;
import com.vimhe.easyimport.processor.DataProcessor;
import com.vimhe.easyimport.util.ValidateUtils;
import com.vimhe.easyimport.validate.DataValidatorChain;
import com.vimhe.easyimport.validate.ErrorMessage;
import com.vimhe.easyimport.validate.ErrorMessageResolver;

import java.util.List;
import java.util.Map;

/**
 * Excel数据读取器
 *
 * @author Vimhe
 */
public class ExcelReader implements IExcelReader {

    private final String fileName;
    private final ImportConfig importConfig;
    private final DataValidatorChain validatorChain;
    private final ErrorMessageResolver messageResolver;
    private final DataFilterChain filterChain;
    private final DataProcessor processor;

    public ExcelReader(String fileName,
                       ImportConfig importConfig,
                       DataValidatorChain validatorChain,
                       ErrorMessageResolver messageResolver,
                       DataFilterChain filterChain,
                       DataProcessor processor) {
        this.fileName = fileName;
        this.importConfig = importConfig;
        this.validatorChain = validatorChain;
        this.messageResolver = messageResolver;
        this.filterChain = filterChain;
        this.processor = processor;
    }

    @Override
    public int getCellCount(int sheetIndex, int rowIndex) {
        RowConfig rowConfig = importConfig.getRowConfig(fileName, sheetIndex, rowIndex);
        if (rowConfig == null) {
            return 0;
        }

        Integer cols = rowConfig.getCols();
        return cols == null ? 0 : cols;
    }

    @Override
    public Object readCell(int sheetIndex, int rowIndex, String cellIndex, Object cellValue) {
        CellConfig cellConfig = importConfig.getCellConfig(fileName, sheetIndex, rowIndex, cellIndex);
        if (cellConfig == null) {
            return null;
        }

        // 调用验证器链对数据进行层层验证
        if (validatorChain != null) {
            List<ErrorMessage> errors = validatorChain.validate(fileName, sheetIndex, rowIndex, cellIndex, cellConfig, cellValue);
            if (ValidateUtils.isEmpty(errors)) {
                // 调用过滤器链对数据进行层层过滤
                if (filterChain != null) {
                    return filterChain.filter(cellConfig, cellValue);
                }

                // 调用数据处理器进行处理
                if (processor != null) {
                    processor.processCell(sheetIndex, rowIndex, cellIndex, cellValue);
                }
            } else {
                // 调用错误处理器进行错误处理
                if (messageResolver != null) {
                    messageResolver.resolve(errors);
                }
            }
        }

        return cellValue;
    }

    @Override
    public Map<String, Object> readRow(int sheetIndex, int rowIndex, Map<String, Object> rowValue) {
        RowConfig rowConfig = importConfig.getRowConfig(fileName, sheetIndex, rowIndex);
        if (rowConfig == null) {
            return null;
        }

        if (processor != null) {
            processor.processRow(sheetIndex, rowIndex, rowValue);
        }

        return rowValue;
    }

    @Override
    public Map<Integer, Map<String, Object>> readSheet(int sheetIndex, Map<Integer, Map<String, Object>> sheetValue) {
        SheetConfig sheetConfig = importConfig.getSheetConfig(fileName, sheetIndex);
        if (sheetConfig == null) {
            return null;
        }

        if (processor != null) {
            processor.processSheet(sheetIndex, sheetValue);
        }

        return sheetValue;
    }

    @Override
    public void readFile(Map<Integer, Map<Integer, Map<String, Object>>> fileValue) {
        FileConfig fileConfig = importConfig.getFileConfig(fileName);
        if (fileConfig == null) {
            return;
        }

        if (processor != null) {
            processor.processFile(fileValue);
        }
    }

}
